import SVGScaler from "../Preprocessors/SVGScaler";
import SVGSizer from "../Preprocessors/SVGSizer";
import { Point } from "../type";
import { ChartSetting, MinMaxInfoSetting, MinMaxLabelRow, MixMaxInfoRow } from "../typeSC";
import Utils from "./utils/Utils";
import pixelWidth from 'string-pixel-width';
import { months } from "./utils/constant";

export default class MinMaxInfo {
    minMaxInfoSetting: MinMaxInfoSetting;
    svgScaler: SVGScaler;
    svgSizer: SVGSizer;

    svg: any;
    el: any;
    position: Point;

    constructor(svg: any, minMaxInfoSetting: MinMaxInfoSetting, svgSizer: SVGSizer, svgScaler: SVGScaler) {
        this.svg = svg;

        this.minMaxInfoSetting = minMaxInfoSetting;
        this.svgScaler = svgScaler;
        this.svgSizer = svgSizer;

        this.position = svgSizer.getPosition(minMaxInfoSetting.id);

        this.el = svg.append('g').attr("data-type", minMaxInfoSetting.id).attr('transform', `translate(${this.position?.x ?? 0}, ${this.position?.y ?? 0})`);
    }

    draw() {
        const arraySettings = this.minMaxInfoSetting['rows'].toReversed();

        for (let i = 0; i < arraySettings.length; i++) {
            const setting = arraySettings[i];

            switch (setting.type) {
                case 'MixMaxInfoRow': {
                    this.addMinMaxRow(setting, i);
                    break;
                }
                case 'MinMaxLabelRow': {
                    this.addLabel(setting, i);
                    break;
                }
            }
        }
    }

    addLabel(setting: MinMaxLabelRow, index: number) {
        const scalersForX = this.svgScaler.getScalers(setting['scale_x_id']);
        const chartData = this.svgScaler.getData(setting['data_id']);

        if (!scalersForX || !chartData) return;

        const length = this.minMaxInfoSetting.rows.length;
        const height = this.minMaxInfoSetting.height;
        const localHeight = this.minMaxInfoSetting.height / length;

        const font = setting['font_family'] ?? 'arial';
        const size = setting['font_size'] ?? 20;

        const xScaler = scalersForX.x([0, this.minMaxInfoSetting.width]);

        const monthMap = Utils.getMinMaxForMonth(chartData.data, 'y', 'x', true) as { [key: string]: { min: { x: any, y: any }, max: { x: any, y: any } }};

        const keys = Object.keys(monthMap).map(item => new Date(`${item}-01T00:00:00.000Z`));

        this.el.append('g').attr('transform', `translate(0, ${height - localHeight * index ?? 0})`).attr("data-type", "min-max-label")
            .call((g: any) => 
                g.selectAll("label").data(keys)
                    .join('text')
                    .text((d: any) => months[d.getMonth()])
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 'bold')
                    .attr("transform", (d: any) => `translate(${xScaler(d) - pixelWidth(months[d.getMonth()], { font: font, bold: true, size: size }) / 2 }, ${- localHeight / 2 + 15 / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black'));
    }

    addMinMaxRow(setting: MixMaxInfoRow, index: number) {
        const scalersForX = this.svgScaler.getScalers(setting['scale_x_id']);
        const chartData = this.svgScaler.getData(setting['data_id']);

        if (!scalersForX || !chartData) return;

        const length = this.minMaxInfoSetting.rows.length;
        const height = this.minMaxInfoSetting.height;
        const localHeight = this.minMaxInfoSetting.height / length;

        const font = setting['font_family'] ?? 'arial';
        const size = setting['font_size'] ?? 13;
        const radius = 5;

        const xScaler = scalersForX.x([0, this.minMaxInfoSetting.width]);

        const monthMap = Utils.getMinMaxForMonth(chartData.data, 'y', 'x', true) as { [key: string]: { min: { x: any, y: any }, max: { x: any, y: any } }};
        
        const widthMap: { [key: string]: number } = {};

        const g = this.el.append('g').attr('transform', `translate(0, ${height - localHeight * index ?? 0})`).attr("data-type", "min-max-row")
            .call((g: any) => 
                g.selectAll("max").data(Object.keys(monthMap))
                    .join('circle')
                    .attr("cx", (d: any) => xScaler(new Date(`${d}-01T00:00:00.000Z`)))
                    .attr("cy", (d: any) => - localHeight / 2 + radius / 2)
                    .attr("data-type", (d: any) => `${d}-00T00:00:00.000Z`)
                    .attr("r", radius)
                    .attr("fill", setting['color'] ?? 'red')
                    .each((d: any) => widthMap[d] = 5 + 10)
            )
            .call((g: any) => 
                g.selectAll("max").data(Object.keys(monthMap))
                    .join('text')
                    .text('max')
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 300)
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d}-01T00:00:00.000Z`)) + widthMap[d] }, ${- localHeight / 2 + 15 / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d] += pixelWidth('max ', { font: font, bold: false, size: size }))

            )
            .call((g: any) => 
                g.selectAll("max").data(Object.entries(monthMap))
                    .join('text')
                    .text((d: any) => Utils.toRound(d[1].max.y, 1))
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 'bold')
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d[0]}-01T00:00:00.000Z`)) + widthMap[d[0]] }, ${- localHeight / 2 + size / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d[0]] += pixelWidth(Utils.toRound(d[1].max.y, 1) + " ", { font: font, bold: true, size: size }))   
            )
            .call((g: any) => 
                g.selectAll("max").data(Object.entries(monthMap))
                    .join('text')
                    .text((d: any) => `(${Utils.formatDate(d[1].max.x.getDate())}.${Utils.formatDate(d[1].max.x.getMonth() + 1)}.)`)
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 300)
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d[0]}-01T00:00:00.000Z`)) + widthMap[d[0]] }, ${- localHeight / 2 + size / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d[0]] += pixelWidth(`(${Utils.formatDate(d[1].max.x.getDate())}.${Utils.formatDate(d[1].max.x.getMonth() + 1)}.)` + " ", { font: font, bold: false, size: size }))   
            )
            .call((g: any) => 
                g.selectAll("max").data(Object.keys(monthMap))
                    .join('text')
                    .text('min')
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 300)
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d}-01T00:00:00.000Z`)) + widthMap[d] + 5 }, ${- localHeight / 2 + size / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d] += pixelWidth('min ', { font: font, bold: false, size: size }) + 5)
            )
            .call((g: any) => 
                g.selectAll("max").data(Object.entries(monthMap))
                    .join('text')
                    .text((d: any) => Utils.toRound(d[1].min.y, 1))
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 'bold')
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d[0]}-01T00:00:00.000Z`)) + widthMap[d[0]] }, ${- localHeight / 2 + size / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d[0]] += pixelWidth(Utils.toRound(d[1].min.y, 1) + " ", { font: font, bold: true, size: size }))   
            )
            .call((g: any) => 
                g.selectAll("max").data(Object.entries(monthMap))
                    .join('text')
                    .text((d: any) => `(${Utils.formatDate(d[1].min.x.getDate())}.${Utils.formatDate(d[1].min.x.getMonth() + 1)}.)`)
                    .attr('class', 'draggable')
                    .attr('font-family', font)
                    .attr('font-size', size)
                    .attr('font-weight', 300)
                    .attr("transform", (d: any) => `translate(${xScaler(new Date(`${d[0]}-01T00:00:00.000Z`)) + widthMap[d[0]] }, ${- localHeight / 2 + 15 / 3 + 1})`)
                    .style("text-anchor", "start")
                    .attr("fill", 'black')
                    .each((d: any) => widthMap[d[0]] += pixelWidth(`(${Utils.formatDate(d[1].min.x.getDate())}.${Utils.formatDate(d[1].min.x.getMonth() + 1)}.)` + " ", { font: font, bold: false, size: size }))   
            )
    }
}